/**
  ******************************************************************************
  * @file    H_I2C_Example.c
  * @author  MTS
  * @version V1.0
  * @date    2023-xx-xx
  * @brief   硬件I2C库使用示例 - MPU6050通信
  ******************************************************************************
  */

#include "stm32f10x.h"
#include "H_I2C.h"

// MPU6050寄存器地址定义
#define MPU6050_ADDR            0xD0    // MPU6050的I2C从机地址
#define MPU6050_WHO_AM_I        0x75    // 器件ID寄存器
#define MPU6050_PWR_MGMT_1      0x6B    // 电源管理寄存器1
#define MPU6050_PWR_MGMT_2      0x6C    // 电源管理寄存器2
#define MPU6050_SMPLRT_DIV      0x19    // 采样率分频寄存器
#define MPU6050_CONFIG          0x1A    // 配置寄存器
#define MPU6050_GYRO_CONFIG     0x1B    // 陀螺仪配置寄存器
#define MPU6050_ACCEL_CONFIG    0x1C    // 加速度计配置寄存器

// 数据寄存器
#define MPU6050_ACCEL_XOUT_H    0x3B
#define MPU6050_ACCEL_XOUT_L    0x3C
#define MPU6050_ACCEL_YOUT_H    0x3D
#define MPU6050_ACCEL_YOUT_L    0x3E
#define MPU6050_ACCEL_ZOUT_H    0x3F
#define MPU6050_ACCEL_ZOUT_L    0x40
#define MPU6050_TEMP_OUT_H      0x41
#define MPU6050_TEMP_OUT_L      0x42
#define MPU6050_GYRO_XOUT_H     0x43
#define MPU6050_GYRO_XOUT_L     0x44
#define MPU6050_GYRO_YOUT_H     0x45
#define MPU6050_GYRO_YOUT_L     0x46
#define MPU6050_GYRO_ZOUT_H     0x47
#define MPU6050_GYRO_ZOUT_L     0x48

// 全局变量
H_I2C_InitTypeDef hI2C;

/**
  * @brief  初始化MPU6050
  * @param  无
  * @retval 无
  */
void MPU6050_Init(void)
{
    // 初始化MPU6050寄存器
    H_I2C_WriteReg(hI2C.I2Cx, MPU6050_ADDR, MPU6050_PWR_MGMT_1, 0x01);    // 电源管理寄存器1，取消睡眠模式，选择时钟源为X轴陀螺仪
    H_I2C_WriteReg(hI2C.I2Cx, MPU6050_ADDR, MPU6050_PWR_MGMT_2, 0x00);    // 电源管理寄存器2，保持默认值0，所有轴均不待机
    H_I2C_WriteReg(hI2C.I2Cx, MPU6050_ADDR, MPU6050_SMPLRT_DIV, 0x09);    // 采样率分频寄存器，配置采样率
    H_I2C_WriteReg(hI2C.I2Cx, MPU6050_ADDR, MPU6050_CONFIG, 0x06);        // 配置寄存器，配置DLPF
    H_I2C_WriteReg(hI2C.I2Cx, MPU6050_ADDR, MPU6050_GYRO_CONFIG, 0x18);   // 陀螺仪配置寄存器，选择满量程为±2000°/s
    H_I2C_WriteReg(hI2C.I2Cx, MPU6050_ADDR, MPU6050_ACCEL_CONFIG, 0x18);  // 加速度计配置寄存器，选择满量程为±16g
}

/**
  * @brief  获取MPU6050的ID
  * @param  无
  * @retval MPU6050的ID
  */
uint8_t MPU6050_GetID(void)
{
    return H_I2C_ReadReg(hI2C.I2Cx, MPU6050_ADDR, MPU6050_WHO_AM_I);
}

/**
  * @brief  获取MPU6050的加速度和陀螺仪数据
  * @param  AccX, AccY, AccZ: 加速度数据指针
  * @param  GyroX, GyroY, GyroZ: 陀螺仪数据指针
  * @retval 无
  */
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ, int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ)
{
    uint8_t buf[14];
    
    // 一次性读取所有数据
    H_I2C_ReadMulti(hI2C.I2Cx, MPU6050_ADDR, MPU6050_ACCEL_XOUT_H, buf, 14);
    
    // 合成数据
    *AccX = (buf[0] << 8) | buf[1];
    *AccY = (buf[2] << 8) | buf[3];
    *AccZ = (buf[4] << 8) | buf[5];
    // buf[6]和buf[7]是温度数据
    *GyroX = (buf[8] << 8) | buf[9];
    *GyroY = (buf[10] << 8) | buf[11];
    *GyroZ = (buf[12] << 8) | buf[13];
}

/**
  * @brief  主函数，程序入口
  * @param  无
  * @retval 无
  */
int main(void)
{
    int16_t AccX, AccY, AccZ, GyroX, GyroY, GyroZ;
    uint8_t id;
    
    // 配置硬件I2C
    hI2C.I2Cx = I2C1;                              // 使用I2C1 (PB6-SCL, PB7-SDA)
    hI2C.ClockSpeed = 400000;                      // 设置时钟速度为400kHz
    hI2C.OwnAddress = 0x00;                        // 设置自身地址
    hI2C.AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // 使用7位地址模式
    
    // 初始化硬件I2C
    H_I2C_Init(&hI2C);
    
    // 初始化MPU6050
    MPU6050_Init();
    
    // 读取MPU6050的ID
    id = MPU6050_GetID();
    
    // 主循环
    while (1)
    {
        // 读取MPU6050数据
        MPU6050_GetData(&AccX, &AccY, &AccZ, &GyroX, &GyroY, &GyroZ);
        
        // 这里可以添加数据处理代码
        
        // 延时
        for (int i = 0; i < 1000000; i++);
    }
}

/******************* (C) COPYRIGHT 2023 MTS *****END OF FILE****/